package smallfrench.moteur.biblio;

import java.util.Arrays;

import smallfrench.moteur.biblio.err.ErreurIndex;
import smallfrench.moteur.interp.RObjet;


/**
 * Un ensemble d’éléments immuable.
 * @author antoine1023
 */
public class ATuple extends AIterable {

	public static class AIterateurTuple extends AIterateur {

		public static final AClasse CLASSE = AClasse.creer(
				AIterateurTuple.class, "IterateurTuple");

		private int i;
		private final RObjet[] tableau;

		@AnnotationMembre
		public AIterateurTuple(RObjet[] tableau) {
			this.tableau = tableau;
		}

		@Override
		@AnnotationMembre
		public RBooleen contientAutres() {
			return RBooleen.nouveau(i < tableau.length);
		}

		@Override
		@AnnotationMembre
		public RObjet suivant() {
			if (i < tableau.length)
				return tableau[i++];
			return RRien.RIEN;
		}

	}

	public static final AClasse CLASSE = AClasse.creer(
			ATuple.class, "Tuple");

	private final RObjet[] tableau;

	@AnnotationMembre(parametresVariables = true)
	public ATuple(RObjet[] tableau) {
		this.tableau = tableau;
	}

	@Override
	@AnnotationMembre
	public AIterateur iterateur() {
		return new AIterateurTuple(tableau);
	}

	@Override
	@AnnotationMembre
	public RChaine enChaine() {
		StringBuilder sb = new StringBuilder("Tuple");
		sb.append('(');
		boolean premier = true;
		for (RObjet i : tableau) {
			if (premier) {
				premier = false;
			} else {
				sb.append(" ; ");
			}
			sb.append(i);
		}
		return new RChaine(sb.append(')').toString());
	}

	@Override
	public boolean equals(Object o) {
		if (! (o instanceof ATuple)) {
			return false;
		}
		ATuple autre = (ATuple) o;
		return Arrays.equals(autre.tableau, tableau);
	}

	@AnnotationMembre
	public RObjet obtenir(REntier element) {
		int index = element.getValeurInt();
		if (index < 0 || index >= tableau.length)
			new ErreurIndex(element).lancer();
		return tableau[index];
	}

	@Override
	public RObjet operateurIndexBase(RObjet autre) {
		if (autre instanceof REntier) {
			REntier entier = (REntier) autre;
			int index = entier.getValeurInt();
			if (index < 0 || index >= tableau.length)
				new ErreurIndex(entier).lancer();
			return tableau[index];
		}
		return null;
	}

	@AnnotationMembre
	public REntier taille() {
		return new REntier(tableau.length);
	}
}
